package com.example.webcomen.Websocket;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import cn.hutool.log.Log;
import com.example.webcomen.Common.AjaxResult;
import com.example.webcomen.Model.AddMessage;
import com.example.webcomen.Model.AddMessageInfo;
import com.example.webcomen.Model.FriendGroup;
import com.example.webcomen.Model.User;
import com.example.webcomen.Service.BaseInfoService;
import com.example.webcomen.Utill.ToInfo;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;



@ServerEndpoint(value = "/webSocket/{username}",encoders = WebSocketEncoder.class)
@Component
public class WebSocketServer {
    private static BaseInfoService baseInfoService;
    @Autowired
    public void setBaseInfoService(BaseInfoService service){
        WebSocketServer.baseInfoService=service;
    }
	 //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineNum = new AtomicInteger();

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<String, Session> sessionPoolsChild = new ConcurrentHashMap<>();

    //发送消息
    public void sendMessage(Session session, String message) throws IOException {
        if(session != null){
            synchronized (session) {
                Log a=Log.get("info");
                a.info("发送信息"+message);
                session.getBasicRemote().sendText(message);
            }
        }
    }
    //发送ajax
    public void sendObject(Session session, HashMap ajaxResult) throws IOException {
        if(session != null){
            synchronized (session) {
                Log a=Log.get("info");
                a.info("发送信息"+ajaxResult.toString());
                try {
                    session.getBasicRemote().sendObject(ajaxResult);
                } catch (EncodeException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //给指定用户发送信息
    public void sendInfo(String userName, String message){
        Session session = sessionPools.get(userName);
        try {
            sendMessage(session, message);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //给指定用户发送信息
    public void sendInfo(String userName, HashMap message){
        Session session = sessionPools.get(userName);
        try {
            sendObject(session, message);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    // 群发消息
    public void broadcast(String message){
    	for (Session session: sessionPools.values()) {
            try {
                sendMessage(session, message);
            } catch(Exception e){
                e.printStackTrace();
                continue;
            }
        }
    }

    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String userName){
        Log a = Log.get("info");
        if(sessionPools.get(userName)==null) {
            sessionPools.put(userName, session);
            addOnlineCount();
            a.info(userName + "加入webSocket！当前人数为" + onlineNum);
        }else {
            sessionPoolsChild.put(userName, session);
            a.info(userName + " 子链接" );
        }
    }

    //关闭连接时调用
    @OnClose
    public void onClose(@PathParam(value = "username") String userName){
        Log a = Log.get("info");
//
        if(sessionPools.get(userName)==null) {
            a.info(userName + "子链接断开"  );
            sessionPoolsChild.remove(userName);
        }else if (sessionPools.get(userName)!=null&&sessionPoolsChild.get(userName)!=null){
            a.info(userName + "主链接未断开，子链接断开"  );
            sessionPoolsChild.remove(userName);
        }else {
            a.info(userName + " 主链接断开" );
            sessionPools.remove(userName);
            subOnlineCount();
            System.out.println(userName + "断开webSocket连接！当前人数为" + onlineNum);
        }

    }

    //收到客户端信息后，根据接收人的username把消息推下去或者群发
    // to=-1群发消息
    @OnMessage
    public void onMessage(String message,Session s) throws IOException{
        if (message.contains("fromUid")&&message.contains("toUid")&&message.contains("groupId")&&message.contains("time")){
            Gson g=new GsonBuilder().setDateFormat("YYYY-mm-dd HH:MM:SS").create();
            AddMessageInfo addMessageInfo=g.fromJson(message,AddMessageInfo.class);

            System.out.println("server get" + addMessageInfo.toString());
            HashMap<String,Object> data=new HashMap<>();
            HashMap<String,Object> otr=new HashMap<>();
            AddMessage addMessage=null;
            User fuser=baseInfoService.selecetUserById(addMessageInfo.getFromUid());
            switch (addMessageInfo.getType()){
//               预准备
                case 2:
                    User user=baseInfoService.selecetUserById(addMessageInfo.getToUid());
                    otr.put("info",addMessageInfo);
                    otr.put("t",user.getUsername());
                    otr.put("a",ToInfo.picToNoStatic(user.getAvatar()));
                    data.put("raw",otr);
                    sendInfo(fuser.getUsername(),data);
                    break;
//                    用户 直接发raw-addMessage 没有info
                case 0:
                    if (addMessageInfo.getGroupId()==null){
//                        新建默认分组
                        addMessageInfo.setGroupId(baseInfoService.createNewFriendGroup("默认分组",
                                addMessageInfo.getFromUid()).getId());;
                    }
                    addMessage= ToInfo.toAddMessage(addMessageInfo);
                    addMessage.setAgree(0);
                    String funame= fuser.getUsername();
                    String tuname=baseInfoService.selecetUserById(addMessage.getToUid()).
                            getUsername();
                    addMessage=baseInfoService.createNewAddMessage(addMessage);
                    if (addMessage!=null) {
//                        提醒收信人更新消息盒子
                        data.put("raw", addMessage);
                        data.put("suc", 0);
//                        告知客户端，服务端已接受消息
                        sendInfo(funame, data);
//                        弹出处理界面
                        sendInfo(tuname, "updateMsg");
                    }else {
                        data.put("e","请勿重复添加好友");
                        sendInfo(funame,data);
                    }
                    break;
//                    群聊
                case 1:
                    addMessage= ToInfo.toAddMessage(addMessageInfo);
                    addMessage.setAgree(0);
                    user=baseInfoService.findHoster(addMessage.getGroupId());
                    addMessage.setToUid(user.getId());
                    data.put("raw",baseInfoService.createNewAddMessage(addMessage));
                    sendInfo(baseInfoService.selecetUserById(addMessage.getToUid()).
                            getUsername(),data);
                    break;
            }
        }else {
            Log a=Log.get("message");
            a.info("new Message");

        }
    }

    //错误时调用
    @OnError
    public void onError(Session session, Throwable throwable){
        System.out.println("发生错误");
        throwable.printStackTrace();
    }

    public static void addOnlineCount(){
        onlineNum.incrementAndGet();
    }

    public static void subOnlineCount() {
        onlineNum.decrementAndGet();
    }
    
    public static AtomicInteger getOnlineNumber() {
        return onlineNum;
    }
    
    public static ConcurrentHashMap<String, Session> getSessionPools() {
        return sessionPools;
    }
}
